home *** CD-ROM | disk | FTP | other *** search
/ Aminet 21 / Aminet 21 (1997)(GTI - Schatztruhe)[!][Oct 1997].iso / Aminet / comm / bbs / cit_src_7H21.lha / ctdl.c < prev    next >
C/C++ Source or Header  |  1997-07-27  |  56KB  |  2,288 lines

  1. /*
  2. *       ctdl.c
  3. *
  4. * Command-interpreter code for Citadel.
  5. */
  6. #define EXTERN
  7. #include "ctdl.h"
  8. #include "global_data.h"   /* all global data in one place */
  9. char QWKmain(void);
  10.  
  11. /* #define NEED_MSG_PEEKING */
  12. /* #define NEED_MSG_LIST */
  13. /*
  14. *       history
  15. *
  16. * 86Aug16 HAW  Kill history from file because of space problems.
  17. * 84May18 JLS/HAW Greeting modified for coherency.
  18. * 84Apr04 HAW  Upgrade to BDS 1.50a begun.
  19. * 83Mar08 CrT  Aide-special functions installed & tested...
  20. * 83Feb24 CrT/SB Menus rearranged.
  21. * 82Dec06 CrT  2.00 release.
  22. * 82Nov05 CrT  removed main() from room2.c and split into sub-fn()s
  23. */
  24. /*
  25. *       Contents
  26. *
  27. * doAide()    handles Aide-only       commands
  28. * doChat()    handles C(hat)    command
  29. * doEnter()   handles E(nter)   command
  30. * doForget()    handles Z(Forget room)  command
  31. * doGoto()    handles G(oto)    command
  32. * doHelp()    handles H(elp)    command
  33. * doKnown()   handles K(nown rooms)   command
  34. * doLogin()   handles L(ogin)   command
  35. * doLogout()    handles T(erminate)     command
  36. * doMeet()    handles M(eet) User command
  37. * doRead()    handles R(ead)    command
  38. * doRegular()   fanout for above commands
  39. * doSkip()    handles S(kip)    command
  40. * doSysop()   handles sysop-only      commands
  41. * doUngoto()    handles U(ngoto)  command
  42. * getCommand()    prints prompt and gets command char
  43. * greeting()    System-entry blurb etc
  44. * main()      has the central menu code
  45. */
  46. static char NoChatAtAll = FALSE;
  47. extern CONFIG     cfg;    /* The main variable to be saved      */
  48. extern aRoom      roomBuf;  /* Room buffer    */
  49. extern MessageBuffer    msgBuf; /* Message buffer   */
  50. extern MessageBuffer    tempMess; /* Message buffer   */
  51. extern logBuffer  logBuf; /* Person's log buffer    */
  52. extern logBuffer  logTmp; /* Person's log buffer    */
  53. extern rTable     *roomTab; /* Room index for RAM   */
  54. extern LogTable   *logTab;  /* Log  index for RAM   */
  55. extern struct floor *FloorTab;
  56. extern long       FDSectCount;  /* size of files in directory   */
  57. extern int    thisRoom; /* Current room   */
  58. extern SECTOR_ID  pulledMLoc; /* Loc of msg to be pulled    */
  59. extern MSG_NUMBER pulledMId;  /* Id of msg to be pulled   */
  60. extern char       *who_str;
  61. extern char       remoteSysop;
  62. extern char       onConsole;  /* Where IO is ...    */
  63. extern char       whichIO;  /* Where IO is ...    */
  64. extern char       outFlag;
  65. extern char       loggedIn; /* Are we logged in?    */
  66. extern char       echo;
  67. extern char       newCarrier; /* Just got carrier, hurrah!    */
  68. extern char       justLostCarrier;/* Boo, hiss!   */
  69. extern char       textDownload; /* flag   */
  70. extern char       haveCarrier;
  71. extern char       *baseRoom;
  72. extern char       heldMess;
  73. extern char       anyEcho;
  74. extern char       PrintBanner;
  75. /*
  76. * doAide()
  77. *
  78. * This function handles the aide-only menu.
  79. *
  80. * return FALSE to fall invisibly into default error msg.
  81. */
  82. char doAide(char moreYet, char first)
  83.   {
  84.   label oldName;
  85.   int  rm;
  86.   char chatStack;
  87.   char fname[100];
  88.   char *ValAide[] =
  89.     {
  90.     "Chat           ", "Delete empty rooms  ", "Edit room\n",
  91.     "Insert message ", "Kill room           ", "S\bNot available.\n",
  92.     "\b", " ", ""
  93.  
  94.     };
  95.   extern char *APrivateRoom;
  96.   extern SListBase Moderators;
  97.   if (roomBuf.rbflags.ISDIR == 1 && HalfSysop())
  98.   ExtraOption(ValAide, "Add File\n");
  99.   if (!aide)
  100.     {
  101.     PushBack('E');
  102.  
  103.     }
  104.   if (moreYet)   first = '\0';
  105.   if (first)     PushBack(first);
  106.  
  107.     SpecialMessage("Status:Aide Functions");
  108.  
  109.   RegisterThisMenu("aide.mnu", ValAide);
  110.   switch (GetMenuChar())
  111.     {
  112.     case 'A':
  113.     getString("EFILEN", fname, sizeof fname, 0);
  114.     if (access(fname, 0) != 0)
  115.       {
  116.       Output_Citadel_Message("NOSUCH",(long)fname,NULL,NULL);   /* no such file */
  117.       break;
  118.  
  119.       };
  120.     if (CopyFile(fname, &roomBuf))
  121.       {
  122.       FileCommentUpdate(fname, FALSE);
  123.  
  124.       };
  125.     break;
  126.     case '\b':
  127.     mPrintf("\b \b"); /* not sure why this is necessary */
  128.     return BACKED_OUT;
  129.     case 'C':
  130.     logMessage(TRIED_CHAT, "", 'C');
  131.     if (NoChatAtAll && !SomeSysop())
  132.       {
  133.       if (!MultiBanner("nochat"))
  134.       tutorial("nochat.blb", TRUE);
  135.  
  136.       }
  137.     else
  138.       {
  139.       chatStack = cfg.BoolFlags.noChat;
  140.       cfg.BoolFlags.noChat = FALSE;
  141.       if (whichIO == MODEM) ringSysop();
  142.       else      interact(TRUE) ;
  143.       cfg.BoolFlags.noChat = chatStack;
  144.  
  145.       }
  146.     break;
  147.     case 'D':
  148.     ZeroMsgBuffer(&msgBuf);
  149.     sPrintf(msgBuf.mbtext, "The following empty rooms deleted by %s: ",
  150.     logBuf.lbname);
  151.     if (!getYesNo("CONFRM"))
  152.     break;
  153.     strCpy(oldName, roomBuf.rbname);
  154.     indexRooms();
  155.     if ((rm=roomExists(oldName)) != ERROR)  getRoom(rm);
  156.     else          getRoom(LOBBY);
  157.     aideMessage(NULL, /* noteDeletedMessage== */ FALSE );
  158.     break;
  159.     case 'E':
  160.     renameRoom();
  161.     break;
  162.     case 'I':
  163.     ZeroMsgBuffer(&msgBuf);
  164.     if (
  165.     thisRoom   == AIDEROOM
  166.     ||
  167.     pulledMId  == 0l
  168.     )
  169.       {
  170.       Output_Citadel_Message("NOMSGI",NULL,NULL,NULL); /* no message insertable*/
  171.       break;
  172.  
  173.       }
  174.     if (!getYesNo("CONFRM"))
  175.     break;
  176.     noteAMessage(roomBuf.msg, MSGSPERRM, pulledMId, pulledMLoc);
  177.     putRoom(thisRoom);
  178.     noteRoom();
  179.     sPrintf(msgBuf.mbtext,"Following message inserted in %s> by %s",
  180.     formRoom(thisRoom, FALSE, FALSE), logBuf.lbname);
  181.     aideMessage(NULL, /* noteDeletedMessage == */ TRUE);
  182.     break;
  183.     case 'K':
  184.     if (
  185.     thisRoom == LOBBY
  186.     ||
  187.     thisRoom == MAILROOM
  188.     ||
  189.     thisRoom == AIDEROOM
  190.     )
  191.       {
  192.       Output_Citadel_Message("NOKILL",NULL,NULL,NULL);
  193.       break;
  194.  
  195.       }
  196.     if (!getYesNo("CONFRM"))   break;
  197.     ZeroMsgBuffer(&msgBuf);
  198.     sPrintf( msgBuf.mbtext, "%s> killed by %s",roomBuf.rbname,logBuf.lbname);
  199.     aideMessage(NULL, /* noteDeletedMessage == */ FALSE);
  200.     KillInfo(roomBuf.rbname);
  201.     roomBuf.rbflags.INUSE = FALSE;
  202.     putRoom(thisRoom);
  203.     noteRoom();
  204.     getRoom(LOBBY);
  205.     break;
  206.     case 'S':
  207.     #ifdef NEED_AVAILABLE
  208.     changeDate();
  209.     #endif
  210.     break;
  211.  
  212.     }
  213.   return GOOD_SELECT;
  214.  
  215.   }
  216. /*
  217. * doChat()
  218. *
  219. * Chatting!
  220. */
  221. char doChat(char moreYet, char first)
  222.   {
  223.   if (moreYet)   first = '\0';
  224.   if (first)     oChar(first);
  225.   if (whichIO != MODEM)
  226.     {
  227.     interact(TRUE) ;
  228.     if (whichIO == CONSOLE)
  229.     if (getYesNo("MODEMM"))
  230.       {
  231.       whichIO = MODEM;
  232.       setUp(FALSE);
  233.       if (!gotCarrier()) EnableModem(FALSE);
  234.  
  235.       }
  236.  
  237.     }
  238.   else
  239.     {
  240.     logMessage(TRIED_CHAT, "", 'C');
  241.     if (cfg.BoolFlags.noChat)
  242.       {
  243.       if (!MultiBanner("nochat"))
  244.       tutorial("nochat.blb", TRUE);
  245.       return GOOD_SELECT;
  246.  
  247.       }
  248.     ringSysop();
  249.  
  250.     }
  251.   return GOOD_SELECT;
  252.  
  253.   }
  254. /*
  255. * doEnter()
  256. *
  257. * This function handles the E(nter) command.
  258. */
  259. char doEnter(char moreYet, char first)
  260.   {
  261.   #define CONFIGURATION   0
  262.   #define MESSAGE   1
  263.   #define PASSWORD  2
  264.   #define ROOM    3
  265.   #define ENTERFILE       4
  266.   #define CONTINUED       5
  267.   #define NETWORK   6
  268.   #define DEFAULT_MESSAGE 7
  269.   char what;      /* one of above seven */
  270.   SListBase  ESelects =
  271.     {
  272.     NULL, FindSelect, NULL, NoFree, NULL
  273.  
  274.     };
  275.   char *EnterOpts[] =
  276.     {
  277.     TERM "\r", TERM "\n", NTERM "Xmodem", NTERM "Ymodem",
  278.     #ifdef WXMODEM_AVAILABLE
  279.     NTERM "Wxmodem",
  280.     #endif
  281.     TERM "Configuration", TERM "Message", TERM "Password",
  282.     TERM "Room", TERM "Held Message", TERM "Net-Message",
  283.     /* These are for external protocols -- don't delete them! */
  284.     " ", " ", " ",
  285.     " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", ""
  286.  
  287.     };
  288.   char abort, Protocol, again;
  289.   char *letter, cmdbuf[30];
  290.   if (loggedIn && roomBuf.rbflags.ISDIR == 1)
  291.   ExtraOption(EnterOpts, TERM "F");
  292.   AddExternProtocolOptions(EnterOpts, TRUE);
  293.   if (moreYet)   first = '\0';
  294.   abort       = FALSE  ;
  295.   if (thisRoom != MAILROOM && !loggedIn &&
  296.   !cfg.BoolFlags.unlogEnterOk)
  297.     {
  298.     Output_Citadel_Message("ENTERM",NULL,NULL,NULL);
  299.     return GOOD_SELECT;
  300.  
  301.     }
  302.   SpecialMessage("Status:Enter");
  303.   if (first)     PushBack(first);
  304.   do
  305.     {
  306.     again = FALSE;
  307.     outFlag = OUTOK;
  308.     Protocol  = ASCII  ;
  309.     what  = DEFAULT_MESSAGE;
  310.     if (CmdMenuList(EnterOpts, &ESelects, "entopt.mnu", cmdbuf,
  311.     moreYet, TRUE) == BACKED_OUT)
  312.     return BACKED_OUT;
  313.     letter = cmdbuf;
  314.     do
  315.       {
  316.       switch (*letter)
  317.         {
  318.         case '\r':
  319.         case '\n':
  320.         break;
  321.         #ifdef WXMODEM_AVAILABLE
  322.         case 'X':
  323.         case 'Y':
  324.         case 'W':
  325.         Protocol = (*letter == 'Y') ? YMDM : (*letter == 'X') ? XMDM : WXMDM;
  326.         break;
  327.         #else
  328.         case 'X':
  329.         case 'Y':
  330.         Protocol = (*letter == 'Y') ? YMDM : XMDM;
  331.         break;
  332.         #endif
  333.         case 'F':
  334.         if (Protocol == ASCII)
  335.           {
  336.           mPrintf("\b\bXmodem F ");
  337.           Protocol = XMDM;
  338.  
  339.           }
  340.         mPrintf("\bile Upload ");
  341.         if (!roomBuf.rbflags.UPLOAD || logBuf.lbflags.TWIT)
  342.           {
  343.           Output_Citadel_Message("NOUPLD",NULL,NULL,NULL);
  344.           abort = TRUE;
  345.  
  346.           }
  347.         what    = ENTERFILE;
  348.         break;
  349.         case 'C':
  350.         again = reconfigure();
  351.         what  = CONFIGURATION;
  352.         break;
  353.         case 'M':
  354.         what  = MESSAGE;
  355.         break;
  356.         case 'P':
  357.         what  = PASSWORD     ;
  358.         break;
  359.         case 'R':
  360.         if (!cfg.BoolFlags.nonAideRoomOk && !aide)
  361.           {
  362.           Output_Citadel_Message("NOTAID",NULL,NULL,NULL);
  363.           abort   = TRUE;
  364.           break;
  365.  
  366.           }
  367.         if (!loggedIn)
  368.           {
  369.           Output_Citadel_Message("LGICRR",NULL,NULL,NULL);
  370.           abort = TRUE;
  371.           break;
  372.  
  373.           }
  374.         if (logBuf.lbflags.TWIT)
  375.           {
  376.           Output_Citadel_Message("TWITNR",NULL,NULL,NULL);
  377.           abort = TRUE;
  378.           break;
  379.  
  380.           }
  381.         what  = ROOM;
  382.         break;
  383.         case 'H':
  384.         what = CONTINUED;
  385.         Protocol   = ASCII; /* can't do this using protocol */
  386.         break;
  387.         case 'N':
  388.         if( logBuf.lbflags.NET_PRIVS )
  389.           what = NETWORK;
  390.         else Output_Citadel_Message("NONETP",NULL, NULL, NULL);
  391.         break;
  392.         default:
  393.         if ((Protocol = FindProtocolCode(*letter, TRUE)) == -1)
  394.         abort = TRUE;
  395.  
  396.         }
  397.       ++letter;
  398.  
  399.       }
  400.     while (moreYet && !abort && *letter);
  401.  
  402.     }
  403.   while (again);
  404.   KillList(&ESelects);
  405.   doCR();
  406.   if (!abort)
  407.     {
  408.     if (whichIO != CONSOLE && loggedIn &&
  409.     (thisRoom == MAILROOM || roomTab[thisRoom].rtflags.ANON))
  410.     echo = CALLER;
  411.     switch (what)
  412.       {
  413.       case DEFAULT_MESSAGE:
  414.       if (Protocol != ASCII)
  415.         {
  416.         Output_Citadel_Message("MSGTRN",NULL,NULL,NULL);
  417.         }
  418.       case   MESSAGE:   makeMessage(Protocol);  break;
  419.       case  PASSWORD:   newPW()   ; break;
  420.       case      ROOM:   makeRoom()    ; break;
  421.       case ENTERFILE:   upLoad(Protocol,NULL,TRUE)  ; break;
  422.       case CONTINUED:   hldMessage(FALSE) ; break;
  423.       case   NETWORK:   netMessage(Protocol); break;
  424.  
  425.       }
  426.     echo = BOTH;
  427.  
  428.     }
  429.   return GOOD_SELECT ;
  430.  
  431.   }
  432. /*
  433. * doForget()
  434. *
  435. * This function handles the (Forget room) command.
  436. */
  437. char doForget(char expand)
  438.   {
  439.   if (!expand)
  440.     {
  441.     mPrintf("%s\n ", roomBuf.rbname);
  442.     if (thisRoom == LOBBY    ||
  443.     thisRoom == MAILROOM ||
  444.     thisRoom == AIDEROOM)
  445.       {
  446.       Output_Citadel_Message("CANTFG",NULL,NULL,NULL);
  447.       return GOOD_SELECT ;
  448.  
  449.       }
  450.     if (!getYesNo("CONFRM"))   return GOOD_SELECT;
  451.     SetKnown(FORGET_OFFSET, 0, thisRoom, &logBuf);
  452.     gotoRoom(baseRoom, 'S');
  453.  
  454.     }
  455.   else
  456.     {
  457.     /* mPrintf("\b\b "); */
  458.     listRooms(FORGOTTEN);
  459.  
  460.     }
  461.   return GOOD_SELECT;
  462.  
  463.   }
  464. /*
  465. * doGoto()
  466. *
  467. * This function handles the G(oto) command.
  468. */
  469. char doGoto(char expand)
  470.   {
  471.   label roomName;
  472.   int   oldRoom;
  473.   outFlag = IMPERVIOUS;
  474.   if (!expand)
  475.     {
  476.     oldRoom = thisRoom;
  477.     gotoRoom("", 'R');
  478.     if (oldRoom == thisRoom && loggedIn && !expert)
  479.     Output_Citadel_Message("NOMMSG",NULL,NULL,NULL);
  480.     return GOOD_SELECT;
  481.  
  482.     }
  483.   if (getNormStr("", roomName, NAMESIZE, BS_VALID) == BACKED_OUT)
  484.     {
  485.     return BACKED_OUT;
  486.  
  487.     }
  488.   if (roomName[0] == '?')
  489.     {
  490.     listRooms(NOT_INTRO);
  491.  
  492.     }
  493.   else
  494.   gotoRoom(roomName, 'R');
  495.   return GOOD_SELECT;
  496.  
  497.   }
  498. /*
  499. * doHelp()
  500. *
  501. * This function the handles the H(elp) command.
  502. */
  503. char doHelp(char expand)
  504.   {
  505.   label fileName;
  506.  
  507.   SpecialMessage("Status:Help");
  508.  
  509.   if (!expand)
  510.     {
  511.     mPrintf("\n\n");
  512.     printHelp("mainhelp.hlp");
  513.     return GOOD_SELECT;
  514.  
  515.     }
  516.   if (getNormStr("", fileName, (sizeof fileName) - 4, BS_VALID) == BACKED_OUT)
  517.   return BACKED_OUT;
  518.   if (strLen(fileName) == 0)
  519.   strCpy(fileName, "mainhelp");
  520.   if (fileName[0] == '?')     printHelp("helpopt.hlp");
  521.   else
  522.     {
  523.     /* adding the extention makes things look simpler for   */
  524.     /* the user... and restricts the files which can be read  */
  525.     strCat(fileName, ".hlp");
  526.     printHelp(fileName);
  527.  
  528.     }
  529.   return GOOD_SELECT;
  530.  
  531.   }
  532. /*
  533. * doKnown()
  534. *
  535. * This function handles the K(nown rooms) command.
  536. */
  537. char doKnown(char expand)
  538.   {
  539.   char select = ERROR, c[2], again;
  540.   label matchstr;
  541.   char *KMenuOpts[] =
  542.     {
  543.     TERM "Anonymous rooms\n", TERM "Match", TERM "Directory rooms\n",
  544.     TERM "Shared rooms\n", TERM "Private rooms\n",
  545.     TERM "Z\bForgotten rooms\n", TERM "Information", TERM "Read-only\n",
  546.     TERM "\r", TERM "\n", ""
  547.  
  548.     };
  549.   SListBase  KSelects =
  550.     {
  551.     NULL, FindSelect, NULL, NoFree, NULL
  552.  
  553.     };
  554.  
  555.   SpecialMessage("Status:Known");
  556.  
  557.   if (!expand)
  558.     {
  559.     mPrintf("\n ");
  560.     listRooms(NOT_INTRO);
  561.  
  562.     }
  563.   else
  564.     {
  565.     do
  566.       {
  567.       again = FALSE;
  568.       if (CmdMenuList(KMenuOpts, &KSelects, "known.mnu", c, TRUE, TRUE)
  569.       == BACKED_OUT)
  570.       return BACKED_OUT;
  571.       switch (c[0])
  572.         {
  573.         case 'I':
  574.         AllInfo();
  575.         break;
  576.         case 'A':
  577.         select = ANON_SEL;
  578.         break;
  579.         case 'M':
  580.         if (getNormStr("",matchstr,NAMESIZE, BS_VALID) == BACKED_OUT)
  581.           {
  582.           again = TRUE;
  583.           select = ERROR;
  584.           PushBack('\b');
  585.           oChar(' ');
  586.  
  587.           }
  588.         else select = MATCH_SEL;
  589.         break;
  590.         case 'D':
  591.         select = DR_SEL;
  592.         break;
  593.         case 'S':
  594.         select = SH_SEL;
  595.         break;
  596.         case 'P':
  597.         select = PR_SEL;
  598.         break;
  599.         case 'Z':
  600.         select = FORGOTTEN;
  601.         break;
  602.         case 'R':
  603.         select = READONLY;
  604.         break;
  605.         case '\r':
  606.         doCR();
  607.         case '\n':
  608.         strCpy(matchstr, "");
  609.         select = MATCH_SEL;
  610.         break;
  611.  
  612.         }
  613.       if (select != MATCH_SEL && select != ERROR)
  614.       listRooms(select);
  615.       else if (select != ERROR)
  616.       searchRooms(matchstr);
  617.  
  618.       }
  619.     while (again);
  620.  
  621.     }
  622.   KillList(&KSelects);
  623.   return GOOD_SELECT;
  624.  
  625.   }
  626. /*
  627. * doLogin()
  628. *
  629. * This function handles the L(ogin) command.
  630. */
  631. char doLogin(char moreYet)
  632.   {
  633.   label passWord;
  634.   if (!moreYet)   mPrintf("\n");
  635.  
  636.   SpecialMessage("Status:Login");
  637.  
  638.   if (loggedIn)
  639.     {
  640.     Output_Citadel_Message("ALRULG",NULL,NULL,NULL);
  641.     return GOOD_SELECT;
  642.  
  643.     }
  644.   echo  = CALLER;
  645.   if (getNormStr(moreYet ? "" : "ULGPWD",
  646.   passWord, NAMESIZE, (moreYet) ? BS_VALID : NO_ECHO) ==
  647.   BACKED_OUT)
  648.     {
  649.     return BACKED_OUT;
  650.  
  651.     }
  652.   echo  = BOTH;
  653.   login(passWord);
  654.   return GOOD_SELECT;
  655.  
  656.   }
  657. /*
  658. * doLogout()
  659. *
  660. * This function handles the T(erminate) command.
  661. */
  662. char doLogout(char expand, char first)
  663.   {
  664.   char cx;
  665.  
  666.   SpecialMessage("Status:Terminating");
  667.  
  668.   if (expand)   first = '\0';
  669.   outFlag = IMPERVIOUS;
  670.   if (heldMess && !cfg.BoolFlags.HoldOnLost)
  671.     {
  672.     Output_Citadel_Message("HOLDMS",NULL,NULL,NULL);
  673.     mAbort(); /* clear any first-run input fromuser */
  674.  
  675.     }
  676.   if (first)   oChar(first);
  677.   if( first )
  678.     {
  679.     cx = first;
  680.  
  681.     }
  682.   else cx = iChar();
  683.   switch (toUpper( cx ))
  684.     {
  685.     case '\b':
  686.     if (expand) return BACKED_OUT;
  687.     default:
  688.     Output_Citadel_Message("LGOPTS",NULL,NULL,NULL);
  689.     break;
  690.     case 'Q':
  691.     mPrintf("uit-also\n ");
  692.     if (!expand)
  693.       {
  694.       if (!getYesNo("CONFRM"))   break;
  695.  
  696.       }
  697.     if (!onLine()) break;
  698.     terminate( /* hangUp == */ TRUE, TRUE);
  699.     break;
  700.     case 'S':
  701.     mPrintf("tay\n ");
  702.     terminate( /* hangUp == */ FALSE, TRUE);
  703.     break;
  704.     case 'A':
  705.     mPrintf("bort\n ");
  706.     terminate( /* hangUp == */ TRUE, FALSE);
  707.  
  708.     }
  709.   outFlag = OUTOK;
  710.   return GOOD_SELECT;
  711.  
  712.   }
  713. OptValues Opt;
  714. char revOrder;  /* Udderly HIDEOUS kludge.  MOOOOOO! */
  715. char PhraseUser;
  716. /*
  717. * doMeet()
  718. *
  719. * This function handles the M(eet) User command.
  720. */
  721. char doMeet(char moreYet)
  722.   {
  723.   label User;
  724.   int   logNo;
  725.  
  726.     SpecialMessage("Status:Meet Users");
  727.  
  728.   if (!moreYet) doCR();
  729.   if (getNormStr(moreYet ? "" : "USMEET",
  730.   User, NAMESIZE, QUEST_SPECIAL | BS_VALID) == BACKED_OUT)
  731.     {
  732.     return BACKED_OUT;
  733.  
  734.     }
  735.   if (strLen(User) != 0)
  736.     {
  737.     if (User[0] == '?')
  738.       {
  739.       BioDirectory();
  740.       return GOOD_SELECT;
  741.  
  742.       }
  743.     logNo = findPerson(User, &logTmp);
  744.     if (logNo == ERROR)
  745.       {
  746.       Output_Citadel_Message("NOPERS",(long)User,NULL,NULL);
  747.       }
  748.     else
  749.       {
  750.       if (GetBioInfo(logNo))
  751.         {
  752.         Output_Citadel_Message("BIOOFU",(long)logTmp.lbname,NULL,NULL);
  753.         doCR();
  754.         mPrintf("%s\n ", msgBuf.mbtext);
  755.  
  756.         }
  757.       else  Output_Citadel_Message("NOBIOU",(long)logTmp.lbname,NULL,NULL);
  758.       }
  759.  
  760.     }
  761.   return GOOD_SELECT;
  762.  
  763.   }
  764. /*
  765. * doRead()
  766. *
  767. * This function handles the R(ead) command.
  768. */
  769. static void *FindUser(char *element, int x);
  770. int   UserOptAdd(char *str);
  771. char doRead(char moreYet, char first)
  772.   {
  773.   char abort = FALSE,
  774.   Compressed = FALSE,
  775.   extDir,
  776.   doDir,
  777.   again,
  778.   hostFile,
  779.   whichMess,
  780.   status = FALSE,
  781.   SrchUser,
  782.   srchPhrase,
  783.   protocol,
  784.   global,
  785.   filestuff = FALSE,
  786.   ReadArchive;
  787.   char *letter, secondletter;
  788.   char fileName[100];
  789.   int    CurRoom;
  790.   extern FILE* upfd;
  791.   SListBase  RSelects =
  792.     {
  793.     NULL, FindSelect, NULL, NoFree, NULL
  794.  
  795.     };
  796.   SListBase  CSelects =
  797.     {
  798.     NULL, FindSelect, NULL, NoFree, NULL
  799.  
  800.     };
  801.   extern char journalMessage, FormatFlag;
  802.   extern int outPut;
  803.   char *ReadOpts[] =
  804.     {
  805.     TERM "\r", TERM "\n",
  806.     #ifdef NO_DeARC_SUPPORT
  807.     TERM "Archive-Directory(s)\n",
  808.     #else
  809.     TERM "Archive",
  810.     #endif
  811.     TERM "Forward", NTERM "Global", NTERM "Local-only", TERM "New",
  812.     TERM "Old-reverse", TERM "Reverse", TERM "Status\n", NTERM "Xmodem",
  813.     #ifdef WXMODEM_AVAILABLE
  814.     NTERM "Wxmodem",
  815.     #endif
  816.     NTERM "Ymodem", NTERM "User", NTERM "Phrase",
  817.     /* these two are here rather than optional due to .RGE/.RGD */
  818.     TERM "Directory", TERM "Extended-Directory", " ", " ", " ", " ",
  819.     " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ",
  820.     " ", " ", " ", " ", " ", ""
  821.  
  822.     };
  823.   #ifndef NO_DeARC_SUPPORT
  824.   char *CompOpts[] =
  825.     {
  826.     TERM "Directory(s)\n", TERM "File(s)\n", TERM "T\bFile(s)\n",
  827.     TERM "B\bFile(s)\n", TERM "\nDirectory(s)", ""
  828.  
  829.     };
  830.   #endif
  831.   char  cmdbuf[40];
  832.   whichMess = NEWoNLY;
  833.   if (moreYet)   first = '\0';
  834.   zero_struct(Opt);
  835.   Opt.Date = -1l;
  836.   InitListValues(&Opt.Users, FindUser, NULL, free, NULL);
  837.   if (thisRoom == MAILROOM && !loggedIn  &&
  838.   !cfg.BoolFlags.unlogReadOk)
  839.     {
  840.     showMessages(whichMess, revOrder,
  841.     logBuf.lbvisit[logBuf.lbgen[thisRoom] & CALLMASK],
  842.     OptionValidate);
  843.     return GOOD_SELECT;
  844.  
  845.     }
  846.   if (!loggedIn  &&  !cfg.BoolFlags.unlogReadOk)
  847.     {
  848.     Output_Citadel_Message("READMM",NULL,NULL,NULL);
  849.     return GOOD_SELECT;
  850.  
  851.     }
  852.   if (first)     PushBack(first);
  853.   if (roomBuf.rbflags.ISDIR == 1 && loggedIn && !logBuf.lbflags.TWIT)
  854.     {
  855.     ExtraOption(ReadOpts, TERM "Binary file(s)");
  856.     ExtraOption(ReadOpts, TERM "Textfile(s)");
  857.  
  858.     }
  859.   if (AnyCompression())
  860.   ExtraOption(ReadOpts, NTERM "Compressed");
  861.   AddExternProtocolOptions(ReadOpts, FALSE);
  862.   if (HalfSysop())
  863.   ExtraOption(ReadOpts, TERM "Invited-users");
  864.  
  865.   SpecialMessage("Status:Reading");
  866.  
  867.   do
  868.     {
  869.     again = FALSE;
  870.     protocol = ASCII;
  871.     whichMess = NEWoNLY;
  872.     extDir = doDir = hostFile = SrchUser = srchPhrase =
  873.     global = ReadArchive = PhraseUser = revOrder = FALSE;
  874.     if (CmdMenuList(ReadOpts, &RSelects, "readopt.mnu", cmdbuf, moreYet, TRUE) ==
  875.     BACKED_OUT)
  876.     return BACKED_OUT;
  877.     letter = cmdbuf;
  878.     do
  879.       {
  880.       outFlag = OUTOK;
  881.       switch (*letter)
  882.         {
  883.         case '\r':
  884.         doCR();
  885.         case '\n':
  886.         break;
  887.         case 'C':
  888.         Compressed = TRUE;
  889.         break;
  890.         case 'A':
  891.         if (   ( global || roomBuf.rbflags.ISDIR )
  892.             && ( logBuf.lbflags.DL_PRIVS || aide ) )
  893.           {
  894.           if (roomBuf.rbflags.DOWNLOAD || HalfSysop())
  895.             {
  896.             if (CmdMenuList(CompOpts, &CSelects, "", cmdbuf, TRUE,
  897.             FALSE) == BACKED_OUT)
  898.               {
  899.               again = TRUE;
  900.               PushBack('\b');
  901.  
  902.               }
  903.             else
  904.               {
  905.               switch (cmdbuf[0])
  906.                 {
  907.                 case '\n':
  908.                 case '\r':
  909.                 case 'D':
  910.                 ReadArchive = 1;
  911.                 break;
  912.                 case 'T':
  913.                 case 'B':
  914.                 case 'F':
  915.                 ReadArchive = 2;
  916.                 break;
  917.                 default:
  918.                 abort = TRUE;
  919.  
  920.                 }
  921.               break;
  922.  
  923.               }
  924.  
  925.             }
  926.           else
  927.             {
  928.             Output_Citadel_Message("NODLDS",NULL,NULL,NULL);
  929.             abort = TRUE;
  930.             break;
  931.  
  932.             }
  933.  
  934.           }
  935.         else
  936.           {
  937.           Output_Citadel_Message("NOTDIR",NULL,NULL,NULL);
  938.           abort = TRUE;
  939.           break;
  940.           };
  941.  
  942.         break;
  943.         case 'F':
  944.         revOrder    = FALSE;
  945.         whichMess   = OLDaNDnEW;
  946.         goto commondate;
  947.         case 'G':
  948.         global  = TRUE;
  949.         break;
  950.         case 'L':
  951.         Opt.LocalOnly = TRUE;
  952.         break;
  953.         case 'N':
  954.         whichMess   = NEWoNLY;
  955.         goto commondate;
  956.         case 'O':
  957.         revOrder    = TRUE;
  958.         whichMess   = OLDoNLY;
  959.         goto commondate;
  960.         case 'R':
  961.         revOrder    = TRUE;
  962.         whichMess   = OLDaNDnEW;
  963.         commondate:
  964.         if (moreYet)
  965.           {
  966.           if (getString("", fileName, NAMESIZE,
  967.           BS_VALID | QUEST_SPECIAL) == BACKED_OUT)
  968.             {
  969.             again = TRUE;
  970.             oChar(' ');
  971.             PushBack('\b');
  972.             break;
  973.  
  974.             }
  975.           if (fileName[0] == '?')
  976.             {
  977.             tutorial("readdate.blb", TRUE);
  978.             KillList(&RSelects);
  979.             return GOOD_SELECT;
  980.  
  981.             }
  982.           if (strLen(fileName) != 0)
  983.           if (ReadDate(fileName, &Opt.Date) == ERROR)
  984.             {
  985.             Output_Citadel_Message("INVLDD",NULL,NULL,NULL);
  986.             KillList(&RSelects);
  987.             return GOOD_SELECT;
  988.  
  989.             }
  990.  
  991.           }
  992.         else
  993.           {
  994.           doCR();
  995.  
  996.           }
  997.         break;
  998.         case 'S':
  999.         status      = TRUE;
  1000.         break;
  1001.         #ifdef WXMODEM_AVAILABLE
  1002.         case 'X':
  1003.         case 'W':
  1004.         case 'Y':
  1005.         protocol    = (*letter == 'W') ? WXMDM :
  1006.         (*letter == 'X') ? XMDM : YMDM;
  1007.         break;
  1008.         #else
  1009.         case 'X':
  1010.         case 'Y':
  1011.         protocol    = (*letter == 'X') ? XMDM : YMDM;
  1012.         break;
  1013.         #endif
  1014.         case 'B':
  1015.         case 'T':
  1016.         filestuff = TRUE;
  1017.         case 'E':
  1018.         case 'D':
  1019.         if (!logBuf.lbflags.DL_PRIVS && !aide)
  1020.           {
  1021.           Output_Citadel_Message("NODLDP",NULL,NULL,NULL);
  1022.           abort = TRUE;
  1023.           break;
  1024.  
  1025.           }
  1026.         if (filestuff)
  1027.           {
  1028.           if (roomBuf.rbflags.DOWNLOAD == 1 || TheSysop() ||
  1029.           remoteSysop)
  1030.             {
  1031.             hostFile      = TRUE ;
  1032.             textDownload    = (*letter == 'T') ? TRUE : FALSE;
  1033.             if (textDownload && protocol == ASCII)
  1034.               {
  1035.               char cx;
  1036.               cx = modIn();
  1037.               switch (secondletter = toUpper(cx))
  1038.                 {
  1039.                 case '\b':
  1040.                 again = TRUE;
  1041.                 PushBack('\b');
  1042.                 break;
  1043.                 case 'F':
  1044.                 mPrintf("Formatted");
  1045.                 FormatFlag = TRUE;
  1046.                 break;
  1047.                 default:
  1048.                 PushBack(secondletter);
  1049.                 case '\r':
  1050.                 case '\n':
  1051.                 case ' ':
  1052.                 doCR();
  1053.  
  1054.                 }
  1055.  
  1056.               }
  1057.  
  1058.             }
  1059.           else
  1060.             {
  1061.             Output_Citadel_Message("NODLDS",NULL,NULL,NULL);
  1062.             abort = TRUE;
  1063.  
  1064.             }
  1065.  
  1066.           }
  1067.         else
  1068.           {
  1069.           if (roomBuf.rbflags.ISDIR == 1 || global)
  1070.             {
  1071.             if (global || roomBuf.rbflags.DOWNLOAD || TheSysop()
  1072.             || remoteSysop)
  1073.               {
  1074.               if (getNormStr("", fileName, sizeof fileName,
  1075.               BS_VALID) == BACKED_OUT)
  1076.                 {
  1077.                 PushBack('\b');
  1078.                 again = TRUE;
  1079.                 oChar(' ');
  1080.                 break;
  1081.  
  1082.                 }
  1083.               if (*letter == 'D') doDir   = TRUE;
  1084.               else      extDir  = TRUE;
  1085.               break;
  1086.  
  1087.               }
  1088.             else
  1089.               {
  1090.               Output_Citadel_Message("NODLDS",NULL,NULL,NULL);
  1091.               abort = TRUE;
  1092.               break;
  1093.  
  1094.               }
  1095.  
  1096.             }
  1097.           else
  1098.             {
  1099.             Output_Citadel_Message("NOTDIR",NULL,NULL,NULL);
  1100.             abort = TRUE;
  1101.  
  1102.             }
  1103.  
  1104.           }
  1105.         break;
  1106.         case 'I':
  1107.         if (doInviteDisplay() == BACKED_OUT)
  1108.           {
  1109.           PushBack('\b');
  1110.           again = TRUE;
  1111.           oChar(' ');
  1112.           break;
  1113.  
  1114.           }
  1115.         KillList(&RSelects);
  1116.         return  GOOD_SELECT;
  1117.         case 'P':
  1118.         srchPhrase = TRUE;
  1119.         PhraseUser = TRUE;
  1120.         break;
  1121.         case 'U':
  1122.         SrchUser = TRUE;
  1123.         PhraseUser = TRUE;
  1124.         break;
  1125.         default:
  1126.         if ((protocol = FindProtocolCode(*letter, FALSE)) == -1)
  1127.         abort = TRUE;
  1128.  
  1129.         }
  1130.       letter++;
  1131.  
  1132.       }
  1133.     while (moreYet && !abort && *letter);
  1134.  
  1135.     }
  1136.   while (again);
  1137.   KillList(&RSelects);
  1138.   KillList(&CSelects);
  1139.   if (abort) return GOOD_SELECT;
  1140.   if (status)
  1141.     {
  1142.     systat();
  1143.     return GOOD_SELECT;
  1144.  
  1145.     }
  1146.   if (ReadArchive)
  1147.     {
  1148.     #ifdef NO_DeARC_SUPPORT
  1149.     getNormStr("ARCHFN", fileName, sizeof fileName, 0);
  1150.     if (srchPhrase)
  1151.     getString("SEARCH", Opt.Phrase, PHRASE_SIZE, 0);
  1152.     mPrintf("\n %7s%8s%5s Name...\n ", "Crunched", "Normal", "date");
  1153.     wildCard(CompressedDir, fileName, TRUE, Opt.Phrase, TRUE);
  1154.     #else
  1155.     if (ReadArchive == 1)
  1156.       {
  1157.       getNormStr("ARCHFN", fileName, sizeof fileName, 0);
  1158.       if (srchPhrase)
  1159.       getString("SEARCH", Opt.Phrase, PHRASE_SIZE, 0);
  1160.       if (strchr(fileName, '.') == NULL) strCat(fileName, ".arc");
  1161.       wildCard(CompressedDir, fileName, TRUE, Opt.Phrase, TRUE);
  1162.  
  1163.       }
  1164.     else if (ReadArchive == 2)
  1165.     SendArcFiles(protocol);
  1166.     #endif
  1167.     return GOOD_SELECT;
  1168.  
  1169.     }
  1170.   if (doDir || extDir)
  1171.     {
  1172.     if (srchPhrase)
  1173.     getString("SEARCH", Opt.Phrase, PHRASE_SIZE, 0);
  1174.     if (!global)
  1175.     doDirectory(doDir, fileName, Opt.Phrase);
  1176.     else
  1177.       {
  1178.       CurRoom = thisRoom;
  1179.       /* should we have tableRunner() do this for us? */
  1180.       for (thisRoom = 0; outFlag == OUTOK && thisRoom < MAXROOMS;
  1181.       thisRoom++)
  1182.       if (roomTab[thisRoom].rtflags.INUSE &&
  1183.       roomTab[thisRoom].rtflags.ISDIR &&
  1184.       (roomTab[thisRoom].rtflags.DOWNLOAD || SomeSysop()) &&
  1185.       knowRoom(&logBuf, thisRoom) == KNOW_ROOM)
  1186.         {
  1187.         getRoom(thisRoom);
  1188.         mPrintf("\n (%s)\n ", roomBuf.rbname);
  1189.         doCR();   /* nice left side now */
  1190.         doDirectory(doDir, fileName, Opt.Phrase);
  1191.         if (outFlag == OUTNEXT) outFlag = OUTOK;
  1192.  
  1193.         }
  1194.       getRoom(CurRoom);
  1195.  
  1196.       }
  1197.     if (journalMessage)
  1198.       {
  1199.       if (redirect(NULL))
  1200.         {
  1201.         doDirectory(doDir, fileName, Opt.Phrase);
  1202.         undirect();
  1203.         /* fclose(upfd);
  1204.         outPut = NORMAL; */
  1205.  
  1206.         }
  1207.       journalMessage = FALSE;
  1208.  
  1209.       }
  1210.     return GOOD_SELECT;
  1211.  
  1212.     }
  1213.   if (hostFile)
  1214.     {
  1215.     if (srchPhrase)
  1216.     getString("SEARCH", Opt.Phrase, PHRASE_SIZE, 0);
  1217.     TranFiles(protocol, Opt.Phrase);
  1218.     FormatFlag = FALSE;
  1219.     return GOOD_SELECT;
  1220.  
  1221.     }
  1222.   if (SrchUser)
  1223.     {
  1224.     getList(UserOptAdd, "Users", NAMESIZE * 3, FALSE);
  1225.  
  1226.     }
  1227.   if (srchPhrase)
  1228.   getString("SEARCH", Opt.Phrase, PHRASE_SIZE, 0);
  1229.   if (Compressed)
  1230.     {
  1231.     if ((Compressed = GetUserCompression()) == NO_COMP)
  1232.     return GOOD_SELECT;
  1233.     doCR();
  1234.  
  1235.     }
  1236.   else Compressed = NO_COMP;
  1237.   download(whichMess, revOrder, protocol, global, Compressed);
  1238.   KillList(&Opt.Users);
  1239.   return GOOD_SELECT;
  1240.  
  1241.   }
  1242. /*
  1243. * UserOptAdd()
  1244. *
  1245. * This adds the given name to a list.
  1246. */
  1247. int UserOptAdd(char *str)
  1248.   {
  1249.   AddData(&Opt.Users, strdup(str), NULL, FALSE);
  1250.   return TRUE;
  1251.  
  1252.   }
  1253. /*
  1254. * FindUser()
  1255. *
  1256. * Is the current user @system _ domain going to match?
  1257. */
  1258. static void *FindUser(char *element, int x)
  1259. /* x is actually not used -- we use global msgBuf */
  1260.   {
  1261.   label User;
  1262.   char System[(2 * NAMESIZE) + 2];
  1263.   System[0] = 0;
  1264.   SepNameSystem(element, User, System, NULL);
  1265.   if (strLen(User) != 0 && matchString(msgBuf.mbauth, User,
  1266.   lbyte(msgBuf.mbauth)) == NULL)
  1267.     {
  1268.     if (strLen(msgBuf.mbto) == 0) return NULL;
  1269.     if (matchString(msgBuf.mbto, User, lbyte(msgBuf.mbto)) == NULL)
  1270.     return NULL;
  1271.  
  1272.     }
  1273.   if (strLen(System) != 0)
  1274.     {
  1275.     if (matchString(msgBuf.mboname, System, lbyte(msgBuf.mboname))
  1276.     == NULL &&
  1277.     matchString(msgBuf.mbdomain, System, lbyte(msgBuf.mbdomain)) == NULL)
  1278.     return NULL;
  1279.  
  1280.     }
  1281.   return element;
  1282.  
  1283.   }
  1284. /*
  1285. * OptionValidate()
  1286. *
  1287. * This is sent to showMessages.
  1288. */
  1289. char OptionValidate(int mode)
  1290.   {
  1291.   if (OptionCheck(mode))
  1292.     {
  1293.     printMessage(0);
  1294.     return Pause_Message_Check();
  1295.  
  1296.     }
  1297.   else mAbort();      /* give a chance to interrupt */
  1298.   return (char)( (mode == 1) ? TRUE : FALSE);
  1299.  
  1300.   }
  1301. /*
  1302. * OptionCheck()
  1303. *
  1304. * This function checks to see if all options fulfilled.
  1305. */
  1306. char OptionCheck(char mode)
  1307.   {
  1308.   long MsgTime;
  1309.   int  rover;
  1310.   if (mode == 1)
  1311.   return (char) (!Opt.LocalOnly && GetFirst(&Opt.Users) == NULL &&
  1312.   strLen(Opt.Phrase) == 0 && Opt.Date == -1l);
  1313.   /* else */
  1314.   /*
  1315.   * If any match failures, don't print.  printMessage(0) indicates a
  1316.   * a print with msg still on disk, while a (1) indicates message now in
  1317.   * the message buffer.
  1318.   */
  1319.   if (Opt.LocalOnly && msgBuf.mboname[0] &&
  1320.   strCmpU(msgBuf.mboname, cfg.codeBuf + cfg.nodeName) != SAMESTRING)
  1321.   return (char)FALSE;
  1322.   if (Opt.Date != -1l)
  1323.   if (ReadDate(msgBuf.mbdate, &MsgTime) != ERROR)
  1324.   if ((!revOrder && MsgTime < Opt.Date) ||
  1325.   (revOrder && MsgTime > Opt.Date))  return (char )FALSE;
  1326.   if (GetFirst(&Opt.Users) != NULL)
  1327.   if (SearchList(&Opt.Users, 0) == NULL) return NULL;
  1328.   if (strLen(Opt.Phrase) != 0)
  1329.     {
  1330.     getMsgStr(getMsgChar, msgBuf.mbtext, MAXTEXT);
  1331.     /* Kill extraneous line breaks */
  1332.     for (rover = 0; msgBuf.mbtext[rover]; rover++)
  1333.     if (msgBuf.mbtext[rover] == NEWLINE &&
  1334.     msgBuf.mbtext[rover + 1] != ' ' &&
  1335.     msgBuf.mbtext[rover + 1] != NEWLINE)
  1336.     msgBuf.mbtext[rover] = ' ';
  1337.     if (matchString(msgBuf.mbtext, Opt.Phrase, lbyte(msgBuf.mbtext))
  1338.     != NULL)
  1339.       {
  1340.       findMessage(msgBuf.mbheadSector, atol(msgBuf.mbId), TRUE);
  1341.       return (char)TRUE;
  1342.  
  1343.       }
  1344.     else return (char)FALSE;
  1345.  
  1346.     }
  1347.   return (char)TRUE;
  1348.  
  1349.   }
  1350. /*
  1351. * doDirectory()
  1352. *
  1353. * This function handles the read directory commands.
  1354. */
  1355. void doDirectory(char doDir, char *fileName, char *phrase)
  1356.   {
  1357.   #ifdef OLD_STYLE
  1358.   extern long BDSizeCount;
  1359.   int   FileCount;
  1360.   if (doDir)
  1361.     {
  1362.     FDSectCount     = 0;      /* global fDir() totals sectors in   */
  1363.     FileCount = wildCard(fDir, fileName, TRUE, phrase, TRUE);
  1364.     mPrintf("\n %d files, approximately %s sectors total\n ", FileCount,
  1365.     PrintPretty(FDSectCount, msgBuf.mbtext));
  1366.  
  1367.     }
  1368.   else
  1369.     {
  1370.     BDSizeCount = 0l;
  1371.     FileCount = wildCard(ShowVerbose, fileName, TRUE, phrase, TRUE);
  1372.     mPrintf("\n %d files, %s bytes total.\n ", FileCount,
  1373.     PrintPretty(BDSizeCount, msgBuf.mbtext));
  1374.  
  1375.     }
  1376.   #else
  1377.   int   FileCount;
  1378.   extern long FDSize;
  1379.   FDSize = 0l;
  1380.   FileCount = wildCard((doDir) ? fDir : ShowVerbose, fileName, TRUE, phrase,
  1381.   TRUE);
  1382.   mPrintf("\n %d files, ", FileCount);
  1383.   mPrintf((doDir) ? "approximately %s sectors total\n " :
  1384.   "%s bytes total.\n ",
  1385.   PrintPretty(FDSize, msgBuf.mbtext));
  1386.   #endif
  1387.   giveSpaceLeft(&roomBuf);
  1388.  
  1389.   }
  1390. #define MAX_USER_ERRORS 25
  1391. /*
  1392. * doRegular()
  1393. *
  1394. * The big fanout.
  1395. */
  1396. char doRegular(char x, char c)
  1397.   {
  1398.   static int errorCount = 0;
  1399.   char       toReturn, cc[2];
  1400.   SListBase  RegSelects =
  1401.     {
  1402.     NULL, FindSelect, NULL, NoFree, NULL
  1403.  
  1404.     };
  1405.   char *RegOpts[] =
  1406.     {
  1407.     TERM "Chat",    TERM "Door",       TERM "!", TERM "Enter",
  1408.     TERM "F\bRead", TERM "Goto",       TERM "+\bGoto",
  1409.     TERM "Read",    TERM "O\bRead",    TERM "N\bRead",
  1410.     TERM "Help",    TERM "Information",TERM "Known rooms",
  1411.     TERM "Login",   TERM "Skip",       TERM "Terminate",
  1412.     TERM "Backup",  TERM "Ungoto",     TERM "-\bBackup",
  1413.     TERM "QWK Mail",TERM "\\",         TERM ";",
  1414.     TERM "Z\bForget", TERM "?",
  1415.      " ",               " ",                ""
  1416.  
  1417.     };
  1418.   char       *legal = "CD!EFG+HIKLMNORSTBU-QZ";
  1419.   toReturn = GOOD_SELECT;
  1420.   if (loggedIn)
  1421.     {
  1422.     if (aide ||(strCmpU(logBuf.lbname,AskForNSMap(&Moderators, thisRoom))  == SAMESTRING ||
  1423.                 strCmpU(logBuf.lbname, FloorTab[thisFloor].FlModerator)    == SAMESTRING))
  1424.         ExtraOption(RegOpts, TERM "Aide special fn:");
  1425.     if (!MeetDisabled)
  1426.       {
  1427.       ExtraOption(RegOpts, TERM "Meet User");
  1428.  
  1429.       }
  1430.     else ExtraOption(RegOpts, TERM "Moo!");
  1431.  
  1432.     };
  1433.    SpecialMessage("Status:User Idle");
  1434.  
  1435.   if (strchr(legal, c) != NULL) errorCount = 0;
  1436.   else        errorCount++;
  1437.   PushBack(c);  /* ugly kludge */
  1438.   if ((cc[0] = c) == 0 ||
  1439.   CmdMenuList(RegOpts, &RegSelects, NULL, cc, x, FALSE) == GOOD_SELECT)
  1440.     {
  1441.     switch (cc[0])
  1442.       {
  1443.       case 'C': toReturn = doChat(  x, '\0');     break;
  1444.       case '!':
  1445.       case 'D': toReturn = doDoor(  x);     break;
  1446.       case 'E': toReturn = doEnter( x, 'M' );     break;
  1447.       case 'F': toReturn = doRead(  x, 'F' );     break;
  1448.       case '+':
  1449.       case 'G': toReturn = doGoto(  x);     break;
  1450.       case 'H': toReturn = doHelp(  x);     break;
  1451.       case 'I': toReturn = doInfo();        break;
  1452.       case 'K': toReturn = doKnown( x);     break;
  1453.       case 'L': toReturn = doLogin( x);     break;
  1454.       case 'M': if (!MeetDisabled) toReturn = doMeet( x); break;
  1455.       case 'N': toReturn = doRead(  x, 'N' );     break;
  1456.       case 'O': toReturn = doRead(  x, 'O' );     break;
  1457.       case 'Q': toReturn = QWKmain();             break;
  1458.       case 'R': toReturn = doRead(  x, 'R' );     break;
  1459.       case 'S': toReturn = doSkip(  x);     break;
  1460.       case 'T': toReturn = doLogout(x, 'Q' );     break;
  1461.       case '-':
  1462.       case 'B': /* k2ne ism */
  1463.       case 'U': toReturn = doUngoto(x);     break;
  1464.       case '\'':
  1465.       case ';': toReturn = DoFloors();      break;
  1466.       case 0:
  1467.       pause(1);          /* To clear line noise */
  1468.       while (MIReady())   inp();   /* eat noise */
  1469.       if (newCarrier)
  1470.         {
  1471.         greeting();
  1472.         newCarrier  = FALSE;
  1473.  
  1474.         }
  1475.       if (justLostCarrier)
  1476.         {
  1477.         justLostCarrier = FALSE;
  1478.         terminate(TRUE, TRUE);
  1479.  
  1480.         }
  1481.       break;  /* irrelevant value */
  1482.       case '?':
  1483.       tutorial("mainopt.mnu", TRUE);
  1484.       if (whichIO == CONSOLE)   mPrintf("\n ^l: SysOp privileged fns\n ");
  1485.       break;
  1486.       case 'A': toReturn = doAide(x, 'E');      break;
  1487.       case 'Z': toReturn = doForget(x);     break;
  1488.       default:
  1489.       if (errorCount > MAX_USER_ERRORS)
  1490.         {
  1491.         logMessage(EVIL_SIGNAL, "", 'E');
  1492.         HangUp(TRUE);
  1493.  
  1494.         }
  1495.       toReturn=BAD_SELECT;
  1496.       break;
  1497.  
  1498.       }
  1499.  
  1500.     }
  1501.   if (toReturn == BACKED_OUT)
  1502.     {
  1503.     PushBack('\b');
  1504.     CmdMenuList(RegOpts, &RegSelects, NULL, cc, FALSE, FALSE);   /* does the BS */
  1505.  
  1506.     }
  1507.   KillList(&RegSelects);
  1508.   return  toReturn;
  1509.  
  1510.   }
  1511. /*
  1512. * doSkip()
  1513. *
  1514. * This function handles the <S>kip a room command.
  1515. */
  1516. char doSkip(char expand)
  1517.   {
  1518.   label roomName;     /* In case of ".Skip" */
  1519.   char  dispbuf[2 * NAMESIZE];
  1520.   int   rover;
  1521.   outFlag = IMPERVIOUS;
  1522.   sPrintf(dispbuf, "%s> goto ", roomTab[thisRoom].rtname);
  1523.   mPrintf("%s", dispbuf);
  1524.   if (expand)
  1525.     {
  1526.     if (getNormStr("", roomName, NAMESIZE, BS_VALID) == BACKED_OUT)
  1527.       {
  1528.       for (rover = 0; rover < strLen(dispbuf); rover++)
  1529.         {
  1530.         mPrintf("\b \b");
  1531.  
  1532.         }
  1533.       return BACKED_OUT;
  1534.  
  1535.       }
  1536.  
  1537.     }
  1538.   else
  1539.   roomName[0] = '\0';
  1540.   if (roomName[0] == '?')
  1541.   tutorial("skip.hlp", TRUE);
  1542.   else
  1543.     {
  1544.     roomTab[thisRoom].rtflags.SKIP = 1;     /* Set bit */
  1545.     gotoRoom(roomName, 'S');
  1546.  
  1547.     }
  1548.   return GOOD_SELECT;
  1549.  
  1550.   }
  1551. /*
  1552. * doSysop()
  1553. *
  1554. * This function handles the sysop-only menu.  It returns FALSE to fall
  1555. * invisibly into default error msg.
  1556. */
  1557. char doSysop()
  1558.   {
  1559.   extern unsigned long S_min, S_max;  /* stack tracking variables */
  1560.   extern char *NoFileStr;
  1561.   MSG_NUMBER  temp;
  1562.   int i;
  1563.   char  systemPW[200];
  1564.  
  1565.  
  1566.   extern char *VERSION, *LCHeld, *netVersion, *SysVers;
  1567.   extern int  fixVers, majorVers;
  1568.   logBuffer   lBuf;   /* This has to be local!  Don't sub logTmp */
  1569.   MenuId  id;
  1570.   char Priv[] = "\n Privileged Functions\n ";
  1571.   char  *CtdlOpts[] =
  1572.     {
  1573.     "A(bort)          ", "B(aud rate)           ", "C(hat mode)\n",
  1574.     "D(ebug mode)     ", "E(cho)                ", "F(ile grab)\n",
  1575.     "I(nformation)    ", "M(ODEM mode)          ", "N(et Menu)\n" ,
  1576.     "O(ther Commands) ", "R(einitialize Modem)  ", "Q(debug)\n",
  1577.     "U(ser Admin)     ", "X(exit from Citadel)\n",
  1578.     #ifdef NEED_MSG_PEEKING
  1579.     "Z ",
  1580.     #endif
  1581.     #ifdef NEED_MSG_LIST
  1582.     "Y ",
  1583.     #endif
  1584.     "1 ",    " W ",    "Z\n",   ""
  1585.  
  1586.     };
  1587.   if ((!onConsole || ConsolePassword) && !remoteSysop)
  1588.     {
  1589.     if (!(onConsole && ConsolePassword && strLen(cfg.sysPassword) == 0))
  1590.       {
  1591.       if ((!aide && !onConsole) || strLen(cfg.sysPassword) == 0)
  1592.         {
  1593.         return BAD_SELECT;
  1594.  
  1595.         }
  1596.       echo  = CALLER;
  1597.       getNormStr("SYSPWD", systemPW, sizeof systemPW, NO_ECHO);
  1598.       echo  = BOTH;
  1599.       if (strCmp(systemPW, cfg.sysPassword) != 0)
  1600.       return BAD_SELECT;
  1601.       remoteSysop = TRUE;
  1602.  
  1603.       }
  1604.  
  1605.     }
  1606.   initLogBuf(&lBuf);
  1607.  
  1608.    SpecialMessage("Status:***Sysop***");
  1609.  
  1610.   if (whichIO == CONSOLE && gotCarrier())
  1611.     Output_Citadel_Message("ONEMOM", NULL, NULL, NULL);
  1612.   id = RegisterSysopMenu("ctdlopt.mnu", CtdlOpts, Priv);
  1613.   while (onLine())
  1614.     {
  1615.     outFlag = OUTOK;
  1616.     SysopMenuPrompt(id, "\n privileged fn: ");
  1617.     switch (GetSysopMenuChar(id))
  1618.       {
  1619.       case 'W':
  1620.       EventShow();  /* Debug stuff */
  1621.       break;
  1622.       case '1':
  1623.       for (i = 0; i < MSGSPERRM; i++)
  1624.         {
  1625.         if (findMessage(roomBuf.msg[i].rbmsgLoc, roomBuf.msg[i].rbmsgNo,
  1626.         TRUE))
  1627.           {
  1628.           mPrintf("(%s : %s) ", msgBuf.mbsrcId, msgBuf.mboname);
  1629.  
  1630.           }
  1631.         mPrintf("%ld: %d\n ", roomBuf.msg[i].rbmsgNo,
  1632.         roomBuf.msg[i].rbmsgLoc);
  1633.  
  1634.         }
  1635.       break;
  1636.       #ifdef NEED_MSG_LIST
  1637.       case 'Y':
  1638.       CloseSysopMenu(id);
  1639.       for (i = 0; i < MSGSPERRM; i++)
  1640.         {
  1641.         mPrintf(" Room:%-20s:%ld: %d\n ",
  1642.         roomBuf.msg[i].rbname,
  1643.         roomBuf.msg[i].rbmsgNo,
  1644.         roomBuf.msg[i].rbmsgLoc);
  1645.         if( (i%20) == 19)iChar();
  1646.  
  1647.         };
  1648.       iChar();
  1649.       id = RegisterSysopMenu("ctdlopt.mnu",CtdlOpts,Priv);
  1650.       break;
  1651.       #endif
  1652.       #ifdef NEED_MSG_PEEKING
  1653.       case 'Z':
  1654.       CloseSysopMenu(id);
  1655.       mPeek();
  1656.       iChar();
  1657.       id = RegisterSysopMenu("ctdlopt.mnu", CtdlOpts,Priv);
  1658.       break;
  1659.       #endif
  1660.       case 'B':
  1661.       changeBauds(id);
  1662.       break;
  1663.       case 'E':
  1664.       sPrintf(systemPW, "%sabled\n ",
  1665.       (anyEcho = !anyEcho) ? "en" : "dis");
  1666.       ScrNewUser();
  1667.       SysopInfoReport(id, systemPW);
  1668.       break;
  1669.       case 'F':
  1670.       SysopRequestString(id, "EFILEN", systemPW, 50, 0);
  1671.       if (!ingestFile(systemPW, &tempMess))
  1672.         {
  1673.         char *fn;
  1674.         fn = strdup(systemPW);
  1675.         sPrintf(systemPW, NoFileStr, fn);
  1676.         SysopError(id, systemPW);
  1677.         free(fn);
  1678.  
  1679.         }
  1680.       break;
  1681.       case 'A':
  1682.       killLogBuf(&lBuf);
  1683.       CloseSysopMenu(id);
  1684.       return GOOD_SELECT;
  1685.       case 'C':
  1686.       cfg.BoolFlags.noChat =  (cfg.BoolFlags.noChat== 1) ? 0 : 1;
  1687.       sPrintf(systemPW, "%sabled\n ",cfg.BoolFlags.noChat ? "dis" : "en" );
  1688.       ScrNewUser();
  1689.       SysopInfoReport(id, systemPW);
  1690.       break;
  1691.       case 'D':
  1692.       cfg.BoolFlags.debug =  (cfg.BoolFlags.debug == 1) ? 0 : 1;
  1693.       sPrintf(systemPW, "%sabled\n ", cfg.BoolFlags.debug ? "en" : "dis");
  1694.       SysopInfoReport(id, systemPW);
  1695.       break;
  1696.       case 'I':
  1697.       sPrintf(msgBuf.mbtext, "\n %s V%s%s\n Net version %s",
  1698.       VARIANT_NAME, VERSION, SysVers, netVersion);
  1699.       sPrintf(lbyte(msgBuf.mbtext), "\n Commands version %d.%d    ", majorVers,
  1700.       fixVers);
  1701.       sPrintf(lbyte(msgBuf.mbtext), "ctdlcnfg.sys version %d\n ",
  1702.       cfg.paramVers);
  1703.       /* sPrintf(lbyte(msgBuf.mbtext), "coreleft is %ld\n ", coreleft()); */
  1704.       sPrintf(lbyte(msgBuf.mbtext), "Stack Usage: Min:%lx Max:%lx Size:%lx\n ",S_min,S_max,(S_max - S_min + 1));
  1705.       if( cfg.Audit != 0)sPrintf(lbyte(msgBuf.mbtext), "You are caller number %ld\n ",Get_Call_Count());
  1706.       sPrintf(lbyte(msgBuf.mbtext), "You have %s privledges\n ",Display_Privledges());
  1707.       ActiveEvents(msgBuf.mbtext);
  1708.       SysopDisplayInfo(id, msgBuf.mbtext, " Info ");
  1709.       break;
  1710.       case 'M':
  1711.       CloseSysopMenu(id);
  1712.       if (whichIO != MODEM)
  1713.         {
  1714.         whichIO = MODEM;
  1715.         setUp(FALSE);
  1716.  
  1717.         }
  1718.       printf("Chat mode %sabled\n ",
  1719.       cfg.BoolFlags.noChat  ?  "dis"  :  "en");
  1720.       if (!gotCarrier())
  1721.         {
  1722.         EnableModem(FALSE);
  1723.         ReInitModem();
  1724.  
  1725.         }
  1726.       #ifdef NEED_VISIBLE
  1727.       if (visibleMode) mPrintf("Visible mode on\n ");
  1728.       #endif
  1729.       killLogBuf(&lBuf);
  1730.       ScrNewUser();
  1731.       startTimer(NEXT_ANYNET);      /* start up anytime net timer */
  1732.       if (gotCarrier()) mPrintf("System on-line\n ");
  1733.       return GOOD_SELECT;
  1734.       case 'O':
  1735.       CloseSysopMenu(id);
  1736.       systemCommands();
  1737.       id = RegisterSysopMenu("ctdlopt.mnu", CtdlOpts,Priv);
  1738.       break;
  1739.       #ifdef MAKE_AVAILABLE
  1740.       case 'S':
  1741.       changeDate();
  1742.       break;
  1743.       #endif
  1744.       #ifdef NEED_VISIBLE
  1745.       case 'V':
  1746.       mPrintf(" VisibleMode==%d\n ",  visibleMode = !visibleMode);
  1747.       break;
  1748.       #endif
  1749.       case ERROR:
  1750.       case 'X':
  1751.       if (!SysopGetYesNo(id, NULL, "CONFRM")) break;
  1752.       ExitToMsdos = TRUE;
  1753.       exitValue   = (remoteSysop && !onConsole) ? REMOTE_SYSOP_EXIT : SYSOP_EXIT;
  1754.       CloseSysopMenu(id);
  1755.       return GOOD_SELECT;
  1756.       case 'N':
  1757.       CloseSysopMenu(id);
  1758.       netStuff();
  1759.       id = RegisterSysopMenu("ctdlopt.mnu", CtdlOpts, Priv);
  1760.       break;
  1761.       case 'R':
  1762.       if (gotCarrier()) HangUp(TRUE);
  1763.       Reinitialize();
  1764.       break;
  1765.       case 'Q':
  1766.       temp = SysopGetNumber(id, "SETOLD", 0l, 200000l);
  1767.       if (temp != 0l) cfg.oldest = temp;
  1768.       break;
  1769.       case 'U':
  1770.       CloseSysopMenu(id);
  1771.       UserAdmin(&lBuf);
  1772.       id = RegisterSysopMenu("ctdlopt.mnu", CtdlOpts,Priv);
  1773.       break;
  1774.  
  1775.       }
  1776.  
  1777.     }
  1778.   killLogBuf(&lBuf);
  1779.   CloseSysopMenu(id);
  1780.   return GOOD_SELECT;
  1781.  
  1782.   }
  1783. /*
  1784. * doUngoto()
  1785. *
  1786. * This function handles the Ungoto command.
  1787. */
  1788. char doUngoto(char moreYet)
  1789.   {
  1790.   label target;
  1791.   if (!moreYet)
  1792.     {
  1793.     strCpy(target, "");
  1794.  
  1795.     }
  1796.   else
  1797.     {
  1798.     if (getNormStr("", target, NAMESIZE, BS_VALID) == BACKED_OUT)
  1799.     return BACKED_OUT;
  1800.  
  1801.     }
  1802.   retRoom(target);
  1803.   return GOOD_SELECT;
  1804.  
  1805.   }
  1806. /*
  1807. * getCommand()
  1808. *
  1809. * This function prints the menu prompt and gets command char and returns a
  1810. * char via parameter and expand flag as value -- i.e., TRUE if parameters
  1811. * follow else FALSE.
  1812. */
  1813. char getCommand(char *c, char bs)
  1814.   {
  1815.   char expand, again;
  1816.   outFlag = OUTOK;
  1817.   if (!bs)
  1818.   givePrompt();
  1819.   do
  1820.     {
  1821.     again = FALSE;
  1822.     /* bizarre cheat */
  1823.     if (!bs)
  1824.       {
  1825.       if( justLostCarrier )
  1826.         {
  1827.         *c = 0;
  1828.  
  1829.         }
  1830.       else
  1831.         {
  1832.         *c = modIn();
  1833.         *c = toUpper(*c);
  1834.  
  1835.         };
  1836.  
  1837.       }
  1838.     else *c = '.';
  1839.     expand  = ( *c == ' ' || *c == '.' || *c == ',' || *c == '/' );
  1840.     if (expand)
  1841.       {
  1842.       if (!bs) oChar(*c);
  1843.       *c = modIn();
  1844.       if ((*c = toUpper(*c)) == '\b')
  1845.         {
  1846.         mPrintf("\b \b");
  1847.         again = TRUE;
  1848.  
  1849.         }
  1850.  
  1851.       }
  1852.     /* catch a late Pause, et al, command */
  1853.     else if (*c == 'P' || *c == '\b') again = TRUE;
  1854.     else if (*c == 7)
  1855.       {
  1856.       if( CheckForSpecial(13,69))netController(0,0,NO_NETS, ANY_CALL,0);
  1857.       }
  1858.     /* else oChar(*c); -- actually, handled somewhere else! */
  1859.     bs = FALSE;
  1860.  
  1861.     }
  1862.   while (again && onLine());
  1863.   if (justLostCarrier)
  1864.     {
  1865.     justLostCarrier = FALSE;
  1866.     terminate(TRUE, TRUE);
  1867.     expand = 0;
  1868.  
  1869.     }
  1870.   return expand;
  1871.  
  1872.   }
  1873. /*
  1874. * greeting()
  1875. *
  1876. * This gives system-entry blurb etc.
  1877. */
  1878. void greeting()
  1879.   {
  1880.   extern char *VERSION, *SysVers;
  1881.   extern int logTries;
  1882.   if (loggedIn) terminate(FALSE, TRUE);
  1883.   setUp(TRUE);     pause(10);
  1884.   logTries = 1; /* put this here instead of setUp() */
  1885.   PrintBanner = TRUE; /* signal for anytime net */
  1886.   doCR();
  1887.   expert = TRUE;
  1888.   HelpIfPresent("banner.pre");
  1889.   if (!MultiBanner("banner"))
  1890.   if (!HelpIfPresent("banner.blb"))
  1891.     Output_Citadel_Message("NODETL",NULL,NULL,NULL);
  1892.   HelpIfPresent("banner.sfx");
  1893.   expert = FALSE;
  1894.   Output_Citadel_Message("VERSIN",NULL,NULL,NULL);
  1895.   Output_Citadel_Message("HELPOP",NULL,NULL,NULL);
  1896.   printf("Chat mode %sabled\n", cfg.BoolFlags.noChat ? "dis" : "en");
  1897.   printf("\n 'MODEM' mode.\n "      );
  1898.   printf("(<ESC> for CONSOLE mode.)\n "   );
  1899.   while (MIReady())
  1900.   inp();
  1901.   gotoRoom(baseRoom, 'R');
  1902.   setUp(TRUE);
  1903.   PrintBanner = FALSE;
  1904.   if (outFlag == NET_CALL)
  1905.     {
  1906.     netController(0, 0, NO_NETS, ANY_CALL, 0);   /* so we don't call out */
  1907.  
  1908.     }
  1909.   else if (outFlag == STROLL_DETECTED)
  1910.     {
  1911.     StrollIt();
  1912.  
  1913.     }
  1914.   outFlag = OUTOK;
  1915.  
  1916.   }
  1917. /*
  1918. * main()
  1919. *
  1920. * This is the main manager.
  1921. */
  1922. void main(int argc, char **argv)
  1923.   {
  1924.   extern char logNetResults, netDebug, DisVandals;
  1925.   extern char netdebuglog;
  1926.   extern char VortexHandle, BpsSet, *kip, ItlWxmodem, Zmodem, NoConsoleBanner;
  1927.   extern int  ParanoiaLimit, LD_Delay;
  1928.   extern long LowFree;
  1929.   char c, x, errMsg;
  1930.   int  CmdResult = GOOD_SELECT;
  1931.   /*
  1932.    initialize global data items
  1933.   */
  1934.   results_debug      = FALSE;    /* debug modem results codes */
  1935.   results_cid        = FALSE;    /* collect caller ID info if present */
  1936.   cfg.weAre          = CITADEL;
  1937.   errMsg             = FALSE;
  1938.   SysVers            = SYSDEP_NAME ;
  1939.   SystemPort         = 0;
  1940.   ExitToMsdos        = FALSE;     /* True when time to bring system down  */
  1941.   exitValue          = CRASH_EXIT;
  1942.   iconify_window     = FALSE;    /* not iconified so printf uses
  1943.                                     crash.sys for output in startup     */
  1944.   R_W_ANY     = "rb+";
  1945.   READ_ANY    = "rb";
  1946.   READ_TEXT   = "ra";
  1947.   APPEND_TEXT = "aa";
  1948.   APPEND_ANY  = "ab";
  1949.   A_C_TEXT    = "ab";
  1950.   WRITE_TEXT  = "wa";
  1951.   W_R_ANY     = "wb+";
  1952.   WRITE_ANY   = "wb";
  1953.  
  1954.   while (argc >= 2)
  1955.     {
  1956.     argc--;
  1957.     if (strCmpU(argv[argc], "+netlog") == SAMESTRING)
  1958.       {
  1959.       logNetResults = TRUE;
  1960.       }
  1961.     else if (strncmp(argv[argc], "+results", 4) == SAMESTRING)
  1962.       {
  1963.       results_debug = TRUE;
  1964.       }
  1965.     else if (strncmp(argv[argc], "+cid", 4) == SAMESTRING)
  1966.       {
  1967.       results_cid   = TRUE;
  1968.       }
  1969.     else if (strncmp(argv[argc], "kip=", 4) == SAMESTRING)
  1970.       {
  1971.       kip = argv[argc] + 4;
  1972.  
  1973.       }
  1974.     else if (strncmp(argv[argc], "lowfree=", 8) == SAMESTRING)
  1975.       {
  1976.       LowFree = atoi(argv[argc] + 8);
  1977.  
  1978.       }
  1979.     else if (strncmp(argv[argc], "lddelay=", 8) == SAMESTRING)
  1980.       {
  1981.       LD_Delay = atoi(argv[argc] + 8);
  1982.  
  1983.       }
  1984.     else if (strncmp(argv[argc], "paranoia=", 9) == SAMESTRING)
  1985.       {
  1986.       if ((ParanoiaLimit = atoi(argv[argc] + 9)) < 1)
  1987.       ParanoiaLimit = 10000;
  1988.  
  1989.       }
  1990.     else if (strncmp(argv[argc], "bps=", 4) == SAMESTRING)
  1991.       {
  1992.       BpsSet = TRUE;
  1993.       ReadBps(argv[argc]);
  1994.  
  1995.       }
  1996.     else if (strCmpU(argv[argc], "+netdebug") == SAMESTRING)
  1997.       {
  1998.       netDebug = TRUE;
  1999.  
  2000.       }
  2001.     else if (strCmpU(argv[argc], "+netdebuglog") == SAMESTRING)
  2002.       {
  2003.       netdebuglog = TRUE;
  2004.  
  2005.       }
  2006.     else if (strCmpU(argv[argc], "+nochat") == SAMESTRING)
  2007.       {
  2008.       NoChatAtAll = TRUE;
  2009.  
  2010.       }
  2011.     else if (strCmpU(argv[argc], "+nomeet") == SAMESTRING)
  2012.       {
  2013.       MeetDisabled = TRUE;
  2014.  
  2015.       }
  2016.     else if (strCmpU(argv[argc], "+noecho") == SAMESTRING)
  2017.       {
  2018.       anyEcho = FALSE;
  2019.  
  2020.       }
  2021.     else if (strCmpU(argv[argc], "+wx") == SAMESTRING)
  2022.       {
  2023.       #ifdef WXMODEM_AVAILABLE
  2024.       ItlWxmodem = TRUE;
  2025.       #endif
  2026.  
  2027.       }
  2028.     else if (strCmpU(argv[argc], "+vortex") == SAMESTRING)
  2029.       {
  2030.       VortexHandle = TRUE;
  2031.  
  2032.       }
  2033.     else if (strCmpU(argv[argc], "-vortex") == SAMESTRING)
  2034.       {
  2035.       VortexHandle = FALSE;
  2036.  
  2037.       }
  2038.     else if (strCmpU(argv[argc], "+vandaloff") == SAMESTRING)
  2039.       {
  2040.       DisVandals = TRUE;
  2041.  
  2042.       }
  2043.     else if (strCmpU(argv[argc], "+conpwd") == SAMESTRING)
  2044.       {
  2045.       ConsolePassword = TRUE;
  2046.  
  2047.       }
  2048.     else if (strCmpU(argv[argc], "+noconban") == SAMESTRING)
  2049.       {
  2050.       NoConsoleBanner = TRUE;
  2051.  
  2052.       }
  2053.     else if (strncmp(argv[argc], "zmodem=", 7) == SAMESTRING)
  2054.       {
  2055.       Zmodem = argv[argc][7];
  2056.  
  2057.       }
  2058.     else
  2059.       {
  2060.       printf("Invalid  argument: %s\n", argv[argc]);
  2061.       errMsg = TRUE;
  2062.  
  2063.       }
  2064.  
  2065.     }
  2066.   if (initCitadel())
  2067.     {
  2068.     greeting();
  2069.     logMessage(FIRST_IN, "", FALSE);
  2070.  
  2071.     }
  2072.   startTimer(NEXT_ANYNET);      /* start anytime net timer */
  2073.   if (errMsg)
  2074.     {
  2075.     sPrintf(msgBuf.mbtext, "System brought up from apparent crash.");
  2076.     aideMessage(NULL,FALSE);
  2077.  
  2078.     }
  2079.   while (!ExitToMsdos)
  2080.     {
  2081.     x       = getCommand(&c, (CmdResult == BACKED_OUT));
  2082.     outFlag = OUTOK;
  2083.     CmdResult = (c==CNTRLl)  ?  doSysop() : doRegular(x, c);
  2084.     if (CmdResult == BAD_SELECT)
  2085.       {
  2086.       Output_Citadel_Message("HLPMNU",NULL,NULL,NULL);
  2087.       }
  2088.  
  2089.     }
  2090.   if (loggedIn)
  2091.   terminate( /* hangUp == */ exitValue == DOOR_EXIT ? FALSE : TRUE, TRUE);
  2092.   logMessage(exitValue != DOOR_EXIT ? LAST_OUT : DOOR_OUT , "", FALSE);
  2093.   writeSysTab();
  2094.   if (onConsole) EnableModem(FALSE);  /* just in case... */
  2095.   if (exitValue != DOOR_EXIT && !cfg.BoolFlags.IsDoor) DisableModem(TRUE);
  2096.   ModemShutdown(((exitValue == DOOR_EXIT || cfg.BoolFlags.IsDoor) && !onConsole) ? FALSE : TRUE);
  2097.   systemShutdown(0);
  2098.   exit(exitValue);
  2099.  
  2100.   }
  2101. /*
  2102. * UserAdmin()
  2103. *
  2104. * This function handles the user administration menu.
  2105. */
  2106. void UserAdmin(logBuffer *lBuf)
  2107.   {
  2108.   extern SListBase MailForward;
  2109.   int      logNo, ltabSlot, result;
  2110.   SYS_FILE killHeld;
  2111.   label    who;
  2112.   MenuId   id;
  2113.   char User_Prompt[] = "\nUser Administration\n ";
  2114.   char     *UserOpts[] =
  2115.     {
  2116.     "A(dd new user)     ", "D(oor privs)  ", "E(ndless User)\n",
  2117.     "F(ile privs)       ", "K(ill user)   ", "N(et privs)\n",
  2118.     "P(rivileges-aide)  ", "T(wit)        ", "X(eXit)\n",
  2119.     ""
  2120.  
  2121.     };
  2122.   id = RegisterSysopMenu("useropt.mnu", UserOpts, User_Prompt);
  2123.   while (onLine())
  2124.     {
  2125.     outFlag = OUTOK;
  2126.     SysopMenuPrompt(id, "\n user admin fn: ");
  2127.     switch (GetSysopMenuChar(id))
  2128.       {
  2129.       case ERROR:
  2130.       case 'X': CloseSysopMenu(id); return ;
  2131.       case 'E': /* permanent account administration */
  2132.       if ((logNo = GetUser(who, lBuf, TRUE)) == ERROR ||
  2133.       logNo == cfg.MAXLOGTAB) break;
  2134.       Output_Citadel_Message((lBuf->lbflags.PERMANENT ? "NPERMA" : "PERMAC")
  2135.                             ,(long)lBuf->lbname,NULL,NULL);
  2136.       if (!SysopGetYesNo(id, NULL, "CONFRM"))   break;
  2137.       lBuf->lbflags.PERMANENT = !lBuf->lbflags.PERMANENT;
  2138.       putLog(lBuf, logNo);
  2139.       /* find position in logTab[] and update that, too */
  2140.       if ((ltabSlot = PWSlot(lBuf->lbpw, /* load == */ FALSE)) != ERROR)
  2141.       logTab[ltabSlot].ltpermanent = lBuf->lbflags.PERMANENT;
  2142.       if (loggedIn  &&  strCmpU(logBuf.lbname, who)==SAMESTRING)
  2143.       logBuf.lbflags.PERMANENT = lBuf->lbflags.PERMANENT;
  2144.       break;
  2145.       case 'T':
  2146.       if ((logNo = GetUser(who, lBuf, TRUE)) == ERROR ||
  2147.       logNo == cfg.MAXLOGTAB) break;
  2148.  
  2149.       Output_Citadel_Message((lBuf->lbflags.TWIT ? "TWITST" : "TWITNT")
  2150.                             ,(long)lBuf->lbname,NULL,NULL);
  2151.       if (!SysopGetYesNo(id, NULL, "CONFRM"))   break;
  2152.  
  2153.       lBuf->lbflags.TWIT = !lBuf->lbflags.TWIT;
  2154.  
  2155.       putLog(lBuf, logNo);
  2156.       if (loggedIn  &&  strCmpU(logBuf.lbname, who)==SAMESTRING)
  2157.       logBuf.lbflags.TWIT = lBuf->lbflags.TWIT;
  2158.       break;
  2159.       case 'F':
  2160.       if ((logNo = GetUser(who, lBuf, TRUE)) == ERROR) break;
  2161.       if (logNo == cfg.MAXLOGTAB)
  2162.         {
  2163.         result = DoAllQuestion("GVFLPR","TAFLPR");
  2164.         if (result == ERROR) break;
  2165.         for (logNo = 0; logNo < cfg.MAXLOGTAB; logNo++)
  2166.           {
  2167.           getLog(lBuf, logNo);
  2168.           if (!onConsole) mPrintf(".");
  2169.           if (lBuf->lbflags.L_INUSE && lBuf->lbflags.DL_PRIVS != result)
  2170.             {
  2171.             lBuf->lbflags.DL_PRIVS = result;
  2172.             putLog(lBuf, logNo);
  2173.  
  2174.             }
  2175.  
  2176.           }
  2177.         break;
  2178.  
  2179.         }
  2180.       Output_Citadel_Message((lBuf->lbflags.DL_PRIVS ? "NFLPRI" : "FILPRI")
  2181.                             ,(long)lBuf->lbname,NULL,NULL);
  2182.       if (!SysopGetYesNo(id, NULL, "CONFRM"))   break;
  2183.  
  2184.       lBuf->lbflags.DL_PRIVS = !lBuf->lbflags.DL_PRIVS;
  2185.       putLog(lBuf, logNo);
  2186.       if (loggedIn  &&  strCmpU(logBuf.lbname, who)==SAMESTRING)
  2187.       logBuf.lbflags.DL_PRIVS = lBuf->lbflags.DL_PRIVS;
  2188.       break;
  2189.       case 'K':
  2190.       if ((logNo = GetUser(who, lBuf, TRUE)) == ERROR ||
  2191.       logNo == cfg.MAXLOGTAB) break;
  2192.       Output_Citadel_Message( "KILLTH",(long)lBuf->lbname,lBuf->credit,NULL);
  2193.       if (!SysopGetYesNo(id, NULL, "CONFRM"))   break;
  2194.       ltabSlot = PWSlot(lBuf->lbpw, /* load == */ FALSE);
  2195.       lBuf->lbname[0] = '\0';
  2196.       lBuf->lbpw[0  ] = '\0';
  2197.       lBuf->lbflags.L_INUSE = FALSE;
  2198.       putLog(lBuf, logNo);
  2199.       logTab[ltabSlot].ltpwhash       = 0;
  2200.       logTab[ltabSlot].ltnmhash       = 0;
  2201.       if (cfg.BoolFlags.HoldOnLost)
  2202.         {
  2203.         sPrintf(msgBuf.mbtext, LCHeld, logNo);
  2204.         makeSysName(killHeld, msgBuf.mbtext, &cfg.holdArea);
  2205.         unlink(killHeld);
  2206.  
  2207.         }
  2208.       KillData(&MailForward, who);
  2209.       UpdateForwarding();
  2210.       break;
  2211.       case 'P':
  2212.       if ((logNo = GetUser(who, lBuf, TRUE)) == ERROR ||
  2213.       logNo == cfg.MAXLOGTAB) break;
  2214.       if (lBuf->lbflags.AIDE == 1)
  2215.         {
  2216.         lBuf->lbflags.AIDE = 0;
  2217.         lBuf->lbgen[AIDEROOM] = ((roomTab[AIDEROOM].rtgen-1) % MAXGEN)
  2218.         << GENSHIFT;
  2219.  
  2220.         }
  2221.       else
  2222.         {
  2223.         lBuf->lbflags.AIDE = 1;
  2224.         lBuf->lbgen[AIDEROOM] = roomTab[AIDEROOM].rtgen << GENSHIFT;
  2225.         lBuf->lbgen[AIDEROOM] += MAXVISIT-1;
  2226.  
  2227.         }
  2228.       Output_Citadel_Message((lBuf->lbflags.AIDE ? "AIDPRI" : "NADPRI" )
  2229.                             ,(long)lBuf->lbname,NULL,NULL);
  2230.       if (!SysopGetYesNo(id, NULL, "CONFRM"))   break;
  2231.       putLog(lBuf, logNo);
  2232.       /* see if it is us: */
  2233.       if (loggedIn  &&  strCmpU(logBuf.lbname, who)==SAMESTRING)
  2234.         {
  2235.         aide = (lBuf->lbflags.AIDE == 1) ? TRUE : FALSE;
  2236.         logBuf.lbgen[AIDEROOM] = lBuf->lbgen[AIDEROOM];
  2237.  
  2238.         }
  2239.       break;
  2240.       case 'D':
  2241.       if ((logNo = GetUser(who, lBuf, TRUE)) == ERROR) break;
  2242.       if (logNo == cfg.MAXLOGTAB)
  2243.         {
  2244.         result = DoAllQuestion("GVDRPR","TADRPR");
  2245.         if (result == ERROR) break;
  2246.         for (logNo = 0; logNo < cfg.MAXLOGTAB; logNo++)
  2247.           {
  2248.           getLog(lBuf, logNo);
  2249.           if (!onConsole) mPrintf(".");
  2250.           if (lBuf->lbflags.L_INUSE && lBuf->lbflags.DOOR_PRIVS != result)
  2251.             {
  2252.             lBuf->lbflags.DOOR_PRIVS = result;
  2253.             putLog(lBuf, logNo);
  2254.  
  2255.             }
  2256.  
  2257.           }
  2258.         break;
  2259.  
  2260.         }
  2261.       lBuf->lbflags.DOOR_PRIVS  = (lBuf->lbflags.DOOR_PRIVS == 1) ? 0 : 1;
  2262.       Output_Citadel_Message((lBuf->lbflags.DOOR_PRIVS ? "DORPRI" : "NDRPRI")
  2263.                             ,(long)lBuf->lbname,NULL,NULL);
  2264.       if (!SysopGetYesNo(id, NULL, "CONFRM"))   break;
  2265.  
  2266.       putLog(lBuf, logNo);
  2267.       /* see if it is us: */
  2268.       if (loggedIn  &&  strCmpU(logBuf.lbname, who)==SAMESTRING)
  2269.         {
  2270.         DoorPriv = lBuf->lbflags.DOOR_PRIVS;
  2271.  
  2272.         }
  2273.       break;
  2274.       case 'N':
  2275.       NetPrivs(who);
  2276.       break;
  2277.       case 'A':
  2278.       CloseSysopMenu(id);
  2279.       newUser(&logTmp);
  2280.       id = RegisterSysopMenu("useropt.mnu", UserOpts, User_Prompt);
  2281.       break;
  2282.  
  2283.       }
  2284.  
  2285.     }
  2286.  
  2287.   }
  2288.